package com.nowcoder.community.service.impl;

import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.AlphaService;
import com.nowcoder.community.util.CommunityUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Date;

@Service
public class AlphaServiceImpl implements AlphaService {

    private static final Logger logger = LoggerFactory.getLogger(AlphaServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DiscussPostMapper discussPostMapper;

    // 由Spring自动创建的一个Bean
    @Autowired
    private TransactionTemplate transactionTemplate;

    public AlphaServiceImpl() {}

    @Override
    // 在类的构造器执行之后调用
    @PostConstruct
    public void init() {}

    @Override
    // 在销毁对象之前调用
    @PreDestroy
    public void destroy() {}

    // REQUIRED: 支持外部事务，如果外部事务不存在则创建新事务
    // REQUIRES_NEW: 创建一个新事务，并未暂停外部十五
    // NESTED: 如果存在外部事务，则嵌套在外部事务中执行（内部事务有独立的提交和回滚），否则就和REQUIRED一样
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    @Override
    public Object save() {
        // 新增用户
        User user = new User();
        user.setUsername("小傻瓜");
        user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
        user.setPassword(CommunityUtil.md5("12345" + user.getSalt()));
        user.setEmail("aabbcc@qq.com");
        user.setHeaderUrl("http://image.nowcoder.com/head/99t.png");
        user.setCreateTime(new Date());
        userMapper.insertUser(user);
        // 新增帖子
        DiscussPost discussPost = new DiscussPost();
        discussPost.setUserId(user.getId());
        discussPost.setTitle("我来啦我操");
        discussPost.setContent("啦啦啦啦啦啦");
        discussPost.setCreateTime(new Date());
        discussPostMapper.insertDiscussPost(discussPost);

        // 故意报个错
        // 验证事务回滚
        Integer.valueOf("abcd");

        return "ok";
    }

    @Override
    public Object save2() {
        transactionTemplate.setIsolationLevel(TransactionTemplate.ISOLATION_READ_COMMITTED);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        return transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 新增用户
                User user = new User();
                user.setUsername("雷克斯");
                user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                user.setPassword(CommunityUtil.md5("12345" + user.getSalt()));
                user.setEmail("a1231335456@qq.com");
                user.setHeaderUrl("http://image.nowcoder.com/head/99t.png");
                user.setCreateTime(new Date());
                userMapper.insertUser(user);
                // 新增帖子
                DiscussPost discussPost = new DiscussPost();
                discussPost.setUserId(user.getId());
                discussPost.setTitle("我来啦kekii");
                discussPost.setContent("我是新人");
                discussPost.setCreateTime(new Date());
                discussPostMapper.insertDiscussPost(discussPost);

                // 故意报个错
                // 验证事务回滚
                Integer.valueOf("abcd");
                return "ok";
            }
        });
    }

    // 这个注解用于:
    // 允许该方法在多线程的环境下, 被异步调用
    /*
    @Async
    public void execute1() {
        logger.debug("execute1: hi thread man");
    }

     */

    /*
    @Scheduled(initialDelay = 10000, fixedRate = 1000)
    public void execute2() {
        logger.debug("execute2: lalala");
    }

     */
}
